(unit-test "store-data" "Verify the store sets and returns data properly"
  (lambda ()
    (define store (make-store (time->timestamp (current-time))))
    (define str "this is a string")
    (define int 1234)
    (define float 3.141526)
    (define fraction 1/3)
    (define function sin)
    (define lst (list (list "a" "b" 1 2 3) (list "c" "d" 4 5 6)))
    (define bool #t)
    (define complex 2+3i)
    (define symbol 'asdf)
    (define u8vec (u8vector 8 7 3 189 23 21 1))
    (define vect (vector 1 2 4 4 3 2 112))
    (define vars (list str int float fraction function lst bool complex symbol u8vec vect))
    (define varn (list "str" "int" "float" "fraction" "function" "lst" "bool" "complex"
                       "symbol" "u8vect" "vect"))
    (set! ##now 0.)
    ;; Set and retrieve all variables
    (set! part1 (let loop ((k varn) (v vars) (pass #t))
      (if (null? k)
        pass
        (begin
          (store-set! store (car k) (car v))
          (loop (cdr k) (cdr v) (and pass (equal? (car v) (store-ref store (car k) #f))))
        )
      )
    ))
    ;; Clear all variables and see if they are gone (and fallback options)
    (store-clear! store varn)
    (set! part2 (fx= 0 (apply + (map (lambda (v) (store-ref store v 0)) varn))))
    ;; Test data store expiry
    (set! part3 (let ((v 31))
      (store-set! store "v" v)
      (and (= (store-timedref store "v" #f) v)
           (begin
             (set! ##now (+ ##now 32))
             (not (store-timedref store "v" #f))
           )
           (= (store-ref store "v" #f) v)
      )
    ))
    ;; Test store category retrieval
    (set! part4 (let ((vars (list "a" "b" "c")))
      (for-each (lambda (v) (store-set! store v v "mycat")) vars)
      (equal? vars (map car (store-listcat store "mycat")))
    ))
    ;; Test timestamps and setnew
    (set! part5 (let ((v 80))
      (store-set! store "ln" v)
      (set! time-before (store-timestamp store "ln"))
      (set! ##now (+ ##now 5))
      (store-setnew! store "ln" v)
      (set! time-after (store-timestamp store "ln"))
      (store-set! store "ln" 1234)
      (set! time-new (store-timestamp store "ln"))
      (and (= time-before time-after) (= time-new (+ time-before 5)))
    ))
    ;; Return the combined test results
    (and part1 part2 part3 part4 part5)
  ))

(unit-test "store-events" "Verify the Event functionality of the store"
  (lambda ()
    (define store (make-store (time->timestamp (current-time))))
    (set! ##now 0.5)
    ;; Event submission and retrival
    (set! part1 (let ((prio 1)
          (id "monitor")
          (payload "alarm"))
      (store-event-add store prio id payload)
      (equal? (list (list 0.5 (string-append id ":" payload) prio)) (store-event-listnew store))
    ))
    ;; Event Graylisting
    (set! part2 (let ((prio 2)
                      (id "monitor")
                      (payload "**alarm**"))
      (set! ##now (+ ##now 120))
      (store-event-add store prio id payload)
      (set! ##now (+ ##now 15))
      (store-event-add store prio id payload)
      (set! ##now (+ ##now 15))
      (store-event-add store prio id payload)
      (set! ##now (+ ##now 15))
      (store-event-add store prio id payload)
      (equal? (list (list 120.5 (string-append id ":" payload) prio)) (store-event-listnew store 120))
    ))
    ;; Make sure none are missed
    (set! part3 (let loop ((i 0))
      (if (fx= i 10000)
        (and (= i (length (store-event-listnew store 150)))
             (= 0 (length (store-event-listnew store ##now))))
        (begin
          (store-event-add store 0 "test" i)
          (set! ##now (+ ##now (random-real)))
          (loop (fx+ i 1))
        )
      )
    ))
    ;; Event Graylisting with longer delays
    (set! part4 (let ((prio 12)
                      (id "monitor")
                      (payload "**alarm**"))
      (set! ##now 10000.5)
      (store-event-add store prio id payload)
      (set! ##now (+ ##now 120))
      (store-event-add store prio id payload)
      (set! ##now (+ ##now 120))
      (store-event-add store prio id payload)
      (set! ##now (+ ##now 120))
      (store-event-add store prio id payload)
      (equal? (list (list 10360.5 (string-append id ":" payload) (fx- prio 10))
                    (list 10000.5 (string-append id ":" payload) (fx- prio 10)))
        (store-event-listnew store 10000))
    ))
    (and part1 part2 part3 part4)
  ))

(unit-test "store-export" "Verify the store exports and imports data properly"
  (lambda ()
    (define erased (for-each destroy-store! (store-list)))
    (define store1 (make-store "store1"))
    (define store2 (make-store "store2"))
    (define str "this is a string")
    (define int 1234)
    (define lst (list (list "a" "b" 1 2 3) (list "c" "d" 4 5 6)))
    (define str2 "and a second one")
    (define int2 6789)
    (define lst2 (list (list "aa" "bb" 11 22 33) (list "cc" "dd" 44 55 66)))
    (define inid "WAVEECG#PluginName")
    (define inv "waveoutput")
    ;; Set all variables
    (store-set! store1 "str" str)
    (store-set! store1 "int" int)
    (store-set! store1 "lst" lst)
    (store-set! store2 "str" str2)
    (store-set! store2 "int" int2)
    (store-set! store2 "lst" lst2)
    ;; set some instance variables
    (store:instance-set! store1 inid inv)
    (store:instance-set! store2 inid inv)
    ;; export the stores
    (set! ts1 (store-timestamp store1 str))
    (set! export (store-export-data))
    (set! part1 (and
      (equal? (store-list) (list store1 store2))
      (equal? (map car export) (store-list))
    ))
    ;; destroy one store and clear the other one
    (destroy-store! store1)
    (store-clear! store2 '("str" "int" "lst"))
    (set! part2 (and
      (equal? (store-list) (list "store2"))
      (not (store-ref store1 "int" #f))
      (not (store-ref store2 "str" #f))
    ))
    ;; import store and see if variables are still there
    ;; and that timestamps were preserved
    (store-import-data export)
    (set! part3 (and
      (equal? (store-list) (list store1 store2))
      (string=? (store-ref store1 "str" "") str)
      (fx= (store-ref store1 "int" -1) int)
      (equal? (store-ref store1 "lst" '()) lst)
      (string=? (store-ref store2 "str" "") str2)
      (fx= (store-ref store2 "int" -1) int2)
      (equal? (store-ref store2 "lst" '()) lst2)
      (fl= (store-timestamp store1 str) ts1)
    ))
    ;; verify we didn't overwrite instance variables
    (set! part4 (and
      (not (store:instance-ref store1 inid))
      (string=? (store:instance-ref store2 inid "") inv)
    ))
    (and part1 part2 part3 part4)
  ))
;;eof
